import { ArrayHelper } from "./arrayHelper";



//泛型
    //有时书写某些函数时，会丢失一些类型信息(多个位置的类型应该保持一致或有关联的信息)，需要依靠泛型。
    //泛型：是指附属于函数，类，接口，类型别名之上的类型
// function take(arr:any[], n:number):any[] {
//     if(n >= arr.length) {
//         return arr
//     }
//     const newArr:any = []
//     for(let i = 0; i < n; i ++) {
//         newArr.push(arr[i])
//     }
//     return newArr
// }
// const newArr = take([3,4,5,6,7,8,9], 3)
// console.log(newArr)


//----------------------------> 在函数中使用泛型 <------------------------


//相当于是一个类型变量，在定义时间，无法预知该变量的类型，只有再调用时，才可以知道他的类型
//  如果无法完成推倒，又没有传递，就默认为空对象类型
// function take<T>(arr:T[], n:number):T[] {
//     if(n >= arr.length) {
//         return arr
//     }
//     const newArr:T[] = []
//     for(let i = 0; i < n; i ++) {
//         newArr.push(arr[i])
//     }
//     return newArr
// }
// const newArr = take<string>(['3','4','5','6','7','8'], 3)
// console.log(newArr)
// const odlArr = take<number>([3,45,6,7,8], 3)
// console.log(odlArr)


// const liArr = take([3,45,6,7,8], 3)
// console.log(liArr)//liArr 被推倒出来是一个number[]


//不传值的话，默认number类型
// function take<T = number>(arr:T[], n:number):T[] {
//     if(n >= arr.length) {
//         return arr
//     }
//     const newArr:T[] = []
//     for(let i = 0; i < n; i ++) {
//         newArr.push(arr[i])
//     }
//     return newArr
// }

//---------------------------------> 在类型别名，接口，类里面使用泛型 <---------------------


//type calback<T> = (n:T, i:number) => boolean; //函数数组的某一项是否否和规定

// interface calback<T> {
//     (n:T, i:number): boolean; 
// } 

// function filter<T>(arr:T[], calback:calback<T>):T[] {
//     const newArr:T[] = []
//     arr.forEach((n, i) => {
//         if(calback(n,i)) {
//             newArr.push(n)
//         }
//     })
//     return newArr
// }
// const arr:number[] = [1,2,4,6,8,9]
// console.log(filter(arr, n => n % 2 !== 0))



//类
//可以通过约束类，去约束类里面所有的函数
// const help = new ArrayHelper([1,2,3,4,5,6])
// help.shuffer()





//------------------------------------------------> 泛型约束 <---------------------------------------------
/**
 * 泛型约束：用于对泛型的约束
 * 将某个对象的name属性的每个单词的首字母大写，然后将该对象返回
 */
//这个时间需要对T进行约束（   因为不知道nameToUppercase中传递的是什么，有没有name的属性，nameToUppercase(111),nameToUppercase(555)   )
//  interface hasNameP {
//      name:string
//  }
// function nameToUppercase<T extends hasNameP>(obj: T):T {
//     obj.name = obj.name[0].toUpperCase()
//     return obj
// }

// let o = {
//     name:"kevin yuan",
//     age:18,
//     gender:"男"
// }
// let newO = nameToUppercase(o)
// console.log(newO)


//------------------------------------------------> 多泛型 <---------------------------------------------
//将两个数组进行混合[1,2,3,4,] ['a','b','c','d']  ==> [1, 'a', 2, 'b', 3, 'c', 4, 'd']

function mininArrary<T, D>(arr1:T[], arr2:D[]):(T|D)[] {
   if(arr1.length !== arr2.length) {
       throw new Error('数组不等')
   } 
   let result:(T|D)[] = []
   arr1.forEach((item, index) => {
      result.push(item)
      result.push(arr2[index])
   })
   return result
}

console.log(mininArrary([1,2,3,4,],['a','b','c','d']))